﻿using La.Code.Log;
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;

namespace LiAnProxy
{

    /// <summary>
    /// 消息委托
    /// </summary>
    /// <param name="str"></param>
    /// <param name="type"></param>
    public delegate void ShowMesHandle(string str, int type);
    /// <summary>
    /// 代理类
    /// </summary>
    public class Proxy
    {


        

        /// <summary>
        /// 消息时间
        /// </summary>
        public event ShowMesHandle ShowMesEvent;

        Socket _clientSocket;
        readonly Byte[] _read = new byte[1024];
        //定义一个空间，存储来自客户端请求数据包
        Byte[] _buffer;
        readonly Encoding _ascii = Encoding.ASCII;

        //设定编码
        readonly Byte[] _recvBytes = new Byte[4096];
        //定义一个空间，存储Web服务器返回的数据
        public Proxy(Socket socket)
        {
            _clientSocket = socket;
        }
        public void Run()
        {

            // 上游 编码格式

            Encoding encoding = Encoding.GetEncoding("utf-8");
            string clientMes = " ";
            //存放来自客户端的HTTP请求字符串
            string url;
            //存放解析出地址请求信息
            int bytes = ReadMessage(_read, ref _clientSocket, ref clientMes);
            if (bytes == 0)
            {
                return;
            }
            int index1 = clientMes.IndexOf(' ');
            int index2 = clientMes.IndexOf(' ', index1 + 1);
            if ((index1 == -1) || (index2 == -1))
            {
                throw new IOException();
            }
            string part1 = clientMes.Substring(index1 + 1, index2 - index1);
            int index3 = part1.IndexOf('/', index1 + 8);
            int index4 = part1.IndexOf(' ', index1 + 8);
            int index5 = index4 - index3;
            url = part1.Substring(index1 + 4, (part1.Length - index5) - 8);
            try
            {
                string[] urlTemp = url.Split(':');
                IPEndPoint ipEndpoint;
                IPAddress ip;
                if (IPAddress.TryParse(urlTemp[0], out ip))
                { //IP地址加端口
                    ipEndpoint = new IPEndPoint(ip, Int32.Parse(urlTemp[1]));

                }
                else
                {
                    //通过域名解析IP
#pragma warning disable 618
                    IPHostEntry ipHost = Dns.Resolve(url);
#pragma warning restore 618
                    Write("远程主机名： " + ipHost.HostName);
                    IPAddress[] address = ipHost.AddressList;
                    Write("Web服务器IP地址：" + address[0]);
                    ipEndpoint = new IPEndPoint(address[0], 80);
                }

                //得到编码格式
                if (clientMes.IndexOf("charset") > -1)
                {
                    string charset =
                        clientMes.Substring(clientMes.IndexOf("charset"),
                            clientMes.LastIndexOf("\r\n") - clientMes.IndexOf("charset"))
                            .Substring(0,
                                clientMes.Substring(clientMes.IndexOf("charset"),
                                    clientMes.LastIndexOf("\r\n") - clientMes.IndexOf("charset")).IndexOf("\r\n"));

                    //  utf-8,gbk,gb2312 
                    string code = charset.Substring(charset.IndexOf('=') + 1, charset.Length - charset.IndexOf('=') - 1);
                    encoding = Encoding.GetEncoding(code);
                }

                //解析出要访问的服务器地址

                Socket psocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //创建连接Web服务器端的Socket对象
                psocket.Connect(ipEndpoint);
                //Socket连Web接服务器
                if (psocket.Connected)
                    Write("Socket 正确连接！");
                string get = clientMes;
                Byte[] byteGet = _ascii.GetBytes(get);
                psocket.Send(byteGet, byteGet.Length, 0);
                //代理访问软件对服务器端传送HTTP请求命令
                Int32 rBytes = psocket.Receive(_recvBytes, _recvBytes.Length, 0);
                //代理访问软件接收来自Web服务器端的反馈信息
                Write("接收字节数：" + rBytes.ToString());
                String strRetPage = encoding.GetString(_recvBytes, 0, rBytes);
                while (rBytes > 0)
                {
                    rBytes = psocket.Receive(_recvBytes, _recvBytes.Length, 0);
                    strRetPage = strRetPage + encoding.GetString(_recvBytes, 0, rBytes);
                }
                psocket.Shutdown(SocketShutdown.Both);
                psocket.Close();
                SendMessage(_clientSocket, strRetPage, encoding);
             //   _clientSocket.Close();
                //代理服务软件往客户端传送接收到的信息
            }
            catch (Exception ex)
            {
                string dd = ex.Message;
                dd += ex.StackTrace;
                // ignored
            }
        }

        //接收客户端的HTTP请求数据
        private int ReadMessage(byte[] byteArray, ref Socket s, ref String clientMes)
        {
            if (clientMes == null) throw new ArgumentNullException("clientMes");
            int bytes = s.Receive(byteArray, 1024, 0);
            string messagefromclient = Encoding.ASCII.GetString(byteArray);
            clientMes = messagefromclient;
            return bytes;
        }

        //传送从Web服务器反馈的数据到客户端
        private void SendMessage(Socket s, string message, Encoding encoding)
        {
            //_buffer = new Byte[message.Length + 1];
            //int length = _ascii.GetBytes(message, 0, message.Length, _buffer, 0);

            _buffer = encoding.GetBytes(message);
            Write("传送字节数：" + _buffer.Length.ToString());
            s.Send(_buffer, _buffer.Length, 0);
          
        }

        void Write(string mes)
        {
            if (ShowMesEvent != null)
                ShowMesEvent(mes, 1);
            //var log = LogFactory.GetLogger(GetType());
            //log.Info(mes);
        }
    }


}
